package com.es.hotel.main.client;

import com.alibaba.fastjson.JSON;
import com.es.hotel.pojo.HotelDoc;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

import static com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type.Text;

@Component
//复杂的查询
public class EsAllDocClient {
    @Autowired
    private EsDocClient esDocClient;

    //查询所有文档
    public void MatchAll() throws IOException {
        SearchRequest request = new SearchRequest("hotel");
        request.source().query(QueryBuilders.matchAllQuery());
        extracted(request);
    }

    //全文检索
    public void MatchAllText() throws IOException {
        SearchRequest request = new SearchRequest("hotel");
        //request.source().query(QueryBuilders.matchQuery("all","儒家"));
        //多个字段的检索
        request.source().query(QueryBuilders.multiMatchQuery("如家","name","business"));
        extracted(request);
    }

    //关键字检索
    public void MatchKeyText() throws IOException {
        SearchRequest request = new SearchRequest("hotel");
        //关键字检索
        //request.source().query(QueryBuilders.termQuery("city","杭州"));
        //范围检索
        request.source().query(QueryBuilders.rangeQuery("price").gte("100").lte(150));
        extracted(request);
    }

    //复合查询
    public void complexText() throws IOException {
        SearchRequest request = new SearchRequest("hotel");
        BoolQueryBuilder booledQuery = QueryBuilders.boolQuery();
        booledQuery.must(QueryBuilders.matchQuery("city", "杭州"));
        booledQuery.filter(QueryBuilders.rangeQuery("price").gte("100").lte(150));
    }

    //排序和分页
    public void sortAndPage() throws IOException {
        int page = 2,size = 20;
        SearchRequest request = new SearchRequest("hotel");
        request.source().query(QueryBuilders.matchAllQuery());
        request.source().sort("price", SortOrder.DESC);
        request.source().from((page-1)*size).size(size);
        extracted(request);
    }

    //高亮结果解析
    public void highlighter() throws IOException {

        //如果 "John" 出现在 "name" 字段中，它会被高亮显示在搜索结果中，即使 "requireFieldMatch" 被设置为 false，其他字段匹配 "John" 的部分也可能被高亮。这在跨字段高亮场景中特别有用。
        // 创建搜索请求
        SearchRequest searchRequest = new SearchRequest("hotel"); // 确保 index 名称是正确的
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        // 设置查询条件
        searchSourceBuilder.query(QueryBuilders.matchQuery("name", "如家"));

        // 设置高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        HighlightBuilder.Field highlightName = new HighlightBuilder.Field("name");
        highlightName.preTags("<highlight>");
        highlightName.postTags("</highlight>");
        highlightBuilder.field(highlightName);
        searchSourceBuilder.highlighter(highlightBuilder);

        // 将高亮和查询设置到搜索请求
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = EsIndexClient.client().search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        SearchHit[] hitsArray = hits.getHits();
        for (SearchHit hit : hitsArray) {
            HotelDoc hotelDoc = JSON.parseObject(hit.getSourceAsString(), HotelDoc.class);
            //高亮处理
            Map<String, HighlightField> map = hit.getHighlightFields();
            if(!CollectionUtils.isEmpty(map)){
                HighlightField highlightField = map.get("name");
                if(highlightField!=null){
                    String highlightedName = Arrays.stream(highlightField.getFragments())
                            .map(org.elasticsearch.common.text.Text::string)
                            .collect(Collectors.joining(" "));
                    hotelDoc.setName(highlightedName);
                    System.out.println("高亮显示的名字: " + hotelDoc.getName());
                    // 输出完整的 hotelDoc 对象，确保 toString() 方法正确覆写
                    System.out.println(hotelDoc);
                }
            }
        }
    }

    //解析返回的结果
    public static void extracted(SearchRequest request) throws IOException {
        SearchResponse response = EsIndexClient.client().search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        long total = hits.getTotalHits().value;
        SearchHit[] hitsArray = hits.getHits();
        for (SearchHit hit : hitsArray) {
            System.out.println("查询到的总条数是："+total);
            System.out.println(hit.getSourceAsString());
        }
    }
}
